<?php
class server extends basic implements remote_export {
	const	STATUS_DISCONNECTED = 0;
	const	STATUS_CONNECTING = 1;
	const	STATUS_RECONNECTING = 2;
	const	STATUS_CONNECTED = 5;
	const	STATUS_IDENTIFIED = 8;
	const	STATUS_ENDOFSYNC = 10;
	public	$users = array(),
			$hub = null,
			$numeric = 0,
			$leafs = array(),
			$status = server::STATUS_DISCONNECTED;
	public function construct(array $pars = null) {
		extract($pars, EXTR_REFS);
		if (!isset($hub))
			$hub = null;
		if (!is_null($hub) and !$hub instanceof server)
			throw new Exepction("invalid hub parameter specified: expected server or null");
		if (!isset($numeric) or !is_int($numeric))
			$numeric = 0;
		if (array_key_exists($this->tolower(),$GLOBALS['servers']))
			throw new Exception("failed to register server $this->name; the name already exists in global server list",016);
		$this->hub =& $hub;
		if ($numeric) {
			$this->numeric = $numeric;
			if (array_key_exists($numeric,$GLOBALS['servers_by_numeric']))
				throw new Exception("failed to register server $name; numeric $numeric in the global server list is taken by server {$GLOBALS['servers_by_numeric'][$numeric]->name}",017);
			$GLOBALS['servers_by_numeric'][$numeric] =& $this;
		}
		$GLOBALS['servers'][$this->tolower()] =& $this;
		if ($hub instanceof server) {
			$hub->register_leaf($this);
		}
	}
	public function destruct($kill_leafs = false) {
		unset($GLOBALS['servers'][$this->tolower()]);
        unset($GLOBALS['basics'][$this->oid()]);
		if ($this->numeric) {
			unset($GLOBALS['servers_by_numeric'][$this->numeric]);
		}
		foreach ($this->leafs as &$leaf) {
            $leaf->hub = null;
			if ($kill_leafs) {
                $leaf->destruct();
			}
			$this->unregister_leaf($leaf);
        }
        if ($this->hub) {
			unset($this->hub->leafs[$this->oid()]);
		}
        $this->drop_users();
	}
	public function __sleep() {
		foreach ($this as $key => &$val) {
			if ($val instanceof remote_export) { //that should catch hub
				$this->static[$key] = new basic_placeholder($val->oid());
			}
		}
		foreach (array('users','leafs') as $arr) {
			$this->static[$arr] = array();
			foreach ($this->$arr as $key => &$val) {
				$this->static[$arr][$key] = new basic_placeholder($val->oid());
			}
		}
		$ret = array('name','oid','static','numeric','status');
		foreach (array('hub') as $obj) {
			if (is_null($this->$obj))
				$ret[] = $obj;
		}
		return $ret;
	}
	public function __wakeup() {
		global $users;
		if (!is_array($users))
			throw new Exception("invalid type of global \$users");
		$users[$this->tolower()] =& $this;
		foreach ($this->static as $key => $static) {
			if ($static instanceof remote_placeholder)
				$this->$key = $static;
			elseif (is_array($static)) {
				$this->$key = array();
				foreach ($static as $skey => $sval) {
					if (!$sval instanceof remote_placeholder) continue;
					$this->$key[$skey] = $sval;
				}
			}
		}
	}
	public function register_leaf(server $leaf) {
		$this->leafs[$leaf->oid()] =& $leaf;
	}
	public function unregister_leaf (server $leaf) {
		unset($this->leafs[$leaf->oid()]);
	}
	public function valid_name($name) {
		return preg_match('/[a-z0-9\.\_/i',$name); //todo improve
	}
	public function drop_users ($reason = '') {
		foreach ($this->users as &$user) {
			$user->destruct($reason);
		}
	}
	public function all_leafs (array &$list) {
		$list[] =& $this;
		foreach ($this->leafs as &$server)
			$server->all_leafs($list);
	}
}
?>
